package org.origin.centre.support.utils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

/**
 * 类型工具类，提供反射相关的类型处理方法
 *
 * @author ferret
 * @version 2024-05-08
 */
@SuppressWarnings("unused")
public final class TypeUtil {

    /**
     * 获取类型的第一个泛型参数
     * @param type 类型
     * @return 泛型参数类型，如果不存在则返回null
     */
    public static Type getTypeArgument(Type type) {
        return getTypeArgument(type, 0);
    }

    /**
     * 获取类型的指定索引的泛型参数
     * @param type 类型
     * @param index 泛型参数的索引
     * @return 泛型参数类型，如果不存在则返回null
     */
    public static Type getTypeArgument(Type type, int index) {
        Type[] typeArguments = getTypeArguments(type);
        return null != typeArguments && typeArguments.length > index ? typeArguments[index] : null;
    }

    /**
     * 获取类型的全部泛型参数
     * @param type 类型
     * @return 泛型参数类型数组，如果不存在则返回null
     */
    public static Type[] getTypeArguments(Type type) {
        if (null == type) {
            return null;
        } else {
            ParameterizedType parameterizedType = toParameterizedType(type);
            return null == parameterizedType ? null : parameterizedType.getActualTypeArguments();
        }
    }

    /**
     * 将类型转换为ParameterizedType
     * @param type 类型
     * @return ParameterizedType，如果无法转换则返回null
     */
    public static ParameterizedType toParameterizedType(Type type) {
        return toParameterizedType(type, 0);
    }

    /**
     * 将类型转换为ParameterizedType，并指定接口索引
     * @param type 类型
     * @param interfaceIndex 接口索引
     * @return ParameterizedType，如果无法转换则返回null
     */
    public static ParameterizedType toParameterizedType(Type type, int interfaceIndex) {
        if (type instanceof ParameterizedType) {
            return (ParameterizedType) type;
        } else {
            if (type instanceof Class) {
                ParameterizedType[] generics = getGenerics((Class<?>) type);
                if (generics.length > interfaceIndex) {
                    return generics[interfaceIndex];
                }
            }
            return null;
        }
    }

    /**
     * 获取类的所有泛型参数
     * @param clazz 类
     * @return 泛型参数的ParameterizedType数组
     */
    public static ParameterizedType[] getGenerics(Class<?> clazz) {
        List<ParameterizedType> result = new ArrayList<>();

        // 获取父类的泛型参数
        Type genericSuper = clazz.getGenericSuperclass();
        if (null != genericSuper && !Object.class.equals(genericSuper)) {
            ParameterizedType parameterizedType = toParameterizedType(genericSuper);
            if (null != parameterizedType) {
                result.add(parameterizedType);
            }
        }

        // 获取接口的泛型参数
        Type[] genericInterfaces = clazz.getGenericInterfaces();
        if (genericInterfaces.length > 0) {
            for (Type genericInterface : genericInterfaces) {
                if (genericInterface instanceof ParameterizedType) {
                    result.add((ParameterizedType) genericInterface);
                }
            }
        }

        return result.toArray(new ParameterizedType[0]);
    }
}
